﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CRL;
using CRL.RedisProvider;
using CRL.Transaction;
using CRL.Transaction.DbStatus;
namespace transTest
{
    class TransInfoManage : BaseProvider<TransMasterInfo>,ITransInfoManage
    {
        public TransMasterInfo QueryChek(TransOptions option)
        {
            return QueryItem(b => b.CheckKey == option.CheckKey);
        }
        public List<TransMasterInfo> QueryChecks(string projectName)
        {
            var db = GetDBExtend();
            return db.QueryList<TransMasterInfo>(b => b.Status != TransStatus.Canceled && b.Status != TransStatus.Commited && b.ProjectName == projectName);
        }
        public void DeleteCompleted()
        {
            var db = GetDBExtend();
            var all = db.QueryList<TransMasterInfo>(b => b.Status == TransStatus.Canceled || b.Status == TransStatus.Commited);
            if (!all.Any())
            {
                return;
            }
            var tids = all.Select(b => b.TId);
            db.Delete<TransMasterInfo>(b => tids.Contains(b.TId));
            db.Delete<TransStepInfo>(b => tids.Contains(b.TId));
        }
        public void UpdateStatus(string tId, TransStatus status, string msg)
        {
            var db = GetDBExtend();
            db.Update<TransMasterInfo>(b => b.TId == tId, new { Status = status, StatusName = status.ToString(), UpdateTime = DateTime.Now, Msg = msg });
        }
        public new void CreateTable()
        {
            var propertyBuilder = new PropertyBuilder<TransMasterInfo>();
            propertyBuilder.AsIndex(b => b.ProjectName);
            propertyBuilder.AsIndex(b => b.TId);
            propertyBuilder.AsIndex(b => b.TransactionType);
            propertyBuilder.Property(b => b.TId).WithColumnLength(50);
            propertyBuilder.Property(b => b.Args).WithColumnLength(5000);
            propertyBuilder.Property(b => b.ArgsType).WithColumnLength(300);
            propertyBuilder.Property(b => b.Name).WithColumnLength(200);
            propertyBuilder.Property(b => b.CheckKey).WithColumnLength(200);

            var propertyBuilder2 = new PropertyBuilder<TransStepInfo>();
            propertyBuilder2.AsIndex(b => b.TId);
            propertyBuilder2.AsIndex(b => b.TransactionType);
            propertyBuilder2.Property(b => b.TId).WithColumnLength(50);
            propertyBuilder2.Property(b => b.Args).WithColumnLength(5000);
            propertyBuilder2.Property(b => b.ArgsType).WithColumnLength(300);
            propertyBuilder2.Property(b => b.Name).WithColumnLength(200);
            propertyBuilder2.Property(b => b.TypeName).WithColumnLength(200);

            var db = GetDBExtend();
            db.CheckTableCreated(typeof(TransMasterInfo));
            db.CheckTableCreated(typeof(TransStepInfo));
        }
        public List<TransStepInfo> QuerySteps(IEnumerable<string> tIds)
        {
            var db = GetDBExtend();
            return db.QueryList<TransStepInfo>(b => tIds.Contains(b.TId));
        }
        public void UpdateStatus(string tId, int stepIndex, TransStatus status, string msg)
        {
            var db = GetDBExtend();
            var step = stepIndex + 1;
            var c = new ParameCollection();
            c["Status"] = status;
            c["StatusName"] = status.ToString();
            c["UpdateTime"] = DateTime.Now;
            c["Msg"] = msg;
            db.Update<TransStepInfo>(b => b.TId == tId && b.Step == step, c);
        }
        public bool SaveSteps(TransMasterInfo info, List<TransStepInfo> steps, out string error)
        {
            error = "";
            var db = GetDBExtend();
            db.BeginTran();
            try
            {
                db.InsertFromObj(info);
                db.BatchInsert(steps);
                db.CommitTran();
                return true;
            }
            catch (Exception e)
            {
                error = e.Message;
                db.RollbackTran();
                return false;
            }
        }
    }

    public class TransInfoManageRedis : ITransInfoManage
    {
        string infoHashId = "TransInfos";
        string stepHashId = "TransSteps_{0}";
        string getStepHashId(string tid)
        {
            return string.Format(stepHashId, tid);
        }
        public TransMasterInfo QueryChek(TransOptions option)
        {
            var client = new RedisClient();
            var tid = client.HGet<string>("TransCheckKeys", option.CheckKey);
            if (string.IsNullOrEmpty(tid))
            {
                return null;
            }
            return client.HGet<TransMasterInfo>(infoHashId, tid);
        }
        public List<TransMasterInfo> QueryChecks(string projectName)
        {
            var client = new RedisClient();
            //状态不为取消和提交成功
            var list = client.HGetAll<TransMasterInfo>(infoHashId).FindAll(b => b.Status != TransStatus.Canceled && b.Status != TransStatus.Commited && b.ProjectName == projectName);
            if (list.Count > 0)
            {
                Console.WriteLine($"TransInfoManage {projectName} 加载任务数{list.Count}");
            }
            return list;
        }
        public void DeleteCompleted()
        {
            var client = new RedisClient();
            var status = new List<TransStatus> { TransStatus.Canceled, TransStatus.Commited };
            var all = client.HGetAll<TransMasterInfo>(infoHashId).FindAll(b => status.Contains(b.Status));
            if (!all.Any())
            {
                return;
            }
            var tids = all.Select(b => b.TId);
            all.ForEach(b =>
            {
                client.HRemove(infoHashId, b.TId);
                client.Remove(getStepHashId(b.TId));
                if (!string.IsNullOrEmpty(b.CheckKey))
                {
                    client.HRemove("TransCheckKeys", b.CheckKey);
                }
            });
        }
        public void UpdateStatus(string tId, TransStatus status, string msg)
        {
            var statusName = status.ToString();
            var client = new RedisClient();
            var info = client.HGet<TransMasterInfo>(infoHashId, tId);
            info.Status = status;
            info.StatusName = statusName;
            info.UpdateTime = DateTime.Now;
            info.Msg = msg;
            client.HSet(infoHashId, tId, info);
        }
        public void CreateTable()
        {

        }
        public List<TransStepInfo> QuerySteps(IEnumerable<string> tIds)
        {
            var client = new RedisClient();
            var list = new List<TransStepInfo>();
            foreach (var tId in tIds)
            {
                var list2 = client.HGetAll<TransStepInfo>(getStepHashId(tId));
                list.AddRange(list2);
            }
            return list;
        }
        public void UpdateStatus(string tId, int stepIndex, TransStatus status, string msg)
        {
            var client = new RedisClient();
            var step = stepIndex + 1;
            var statusName = status.ToString();
            var stepInfo = client.HGet<TransStepInfo>(getStepHashId(tId), step.ToString());
            stepInfo.Status = status;
            stepInfo.StatusName = statusName;
            stepInfo.UpdateTime = DateTime.Now;
            stepInfo.Msg = msg;
            client.HSet(getStepHashId(tId), step.ToString(), stepInfo);
        }
        public bool SaveSteps(TransMasterInfo info, List<TransStepInfo> steps, out string error)
        {
            error = "";
            var client = new RedisClient();
            client.HSet(infoHashId, info.TId, info);
            var values = steps.ToDictionary(b => b.Step.ToString(), b => (object)b);
            client.HSet(getStepHashId(info.TId), values);
            if (!string.IsNullOrEmpty(info.CheckKey))
            {
                client.HSet("TransCheckKeys", info.CheckKey, info.TId);
            }
            return true;
        }
    }
}
